﻿using SD.Infrastructure.EntityBase;
using SD.OpcProxy.ValueObjects;
using SD.OpcProxy.ValueObjects.Enums;
using SD.Toolkits.Json;
using System;
using System.Collections.Generic;
using System.Text;

namespace SD.OpcProxy.Domain.Entities
{
    /// <summary>
    /// 变量
    /// </summary>
    public class Variable : AggregateRootEntity
    {
        #region # 构造器

        #region 00.无参构造器
        /// <summary>
        /// 无参构造器
        /// </summary>
        protected Variable() { }
        #endregion

        #region 01.创建变量构造器
        /// <summary>
        /// 创建变量构造器
        /// </summary>
        /// <param name="variableNo">变量编号</param>
        /// <param name="variableName">变量名称</param>
        /// <param name="variableType">变量类型</param>
        /// <param name="isReadonly">是否只读</param>
        /// <param name="dataType">数据类型</param>
        /// <param name="opcServerId">OPC服务器Id</param>
        /// <param name="unit">单位</param>
        /// <param name="keepRecord">是否记录历史</param>
        /// <param name="description">描述</param>
        /// <param name="valueDescriptions">值描述字典</param>
        public Variable(string variableNo, string variableName, VariableType variableType, bool isReadonly, string dataType, Guid opcServerId, string unit, bool keepRecord, string description, IDictionary<string, string> valueDescriptions)
            : this()
        {
            #region # 验证

            if (variableType == VariableType.Internal)
            {
                opcServerId = Constants.OpcProxyServerId;
            }
            if (!Constants.AvailableTypes.Keys.Contains(dataType))
            {
                throw new ArgumentOutOfRangeException(nameof(dataType), "数据类型不存在！");
            }

            #endregion

            base.Number = variableNo;
            base.Name = variableName;
            this.VariableType = variableType;
            this.IsReadonly = isReadonly;
            this.DataType = dataType;
            this.OpcServerId = opcServerId;
            this.Unit = unit;
            this.KeepRecord = keepRecord;
            this.Description = description;
            this.ValueDescriptionsStr = valueDescriptions?.ToJson();

            //初始化关键字
            this.InitKeywords();
        }
        #endregion

        #endregion

        #region # 属性

        #region 变量类型 —— VariableType VariableType
        /// <summary>
        /// 变量类型
        /// </summary>
        public VariableType VariableType { get; private set; }
        #endregion

        #region 是否只读 —— bool IsReadonly
        /// <summary>
        /// 是否只读
        /// </summary>
        public bool IsReadonly { get; private set; }
        #endregion

        #region 数据类型 —— string DataType
        /// <summary>
        /// 数据类型
        /// </summary>
        public string DataType { get; private set; }
        #endregion

        #region OPC服务器Id —— Guid OpcServerId
        /// <summary>
        /// OPC服务器Id
        /// </summary>
        public Guid OpcServerId { get; private set; }
        #endregion

        #region 单位 —— string Unit
        /// <summary>
        /// 单位
        /// </summary>
        public string Unit { get; private set; }
        #endregion

        #region 是否记录历史 —— bool KeepRecord
        /// <summary>
        /// 是否记录历史
        /// </summary>
        public bool KeepRecord { get; private set; }
        #endregion

        #region 描述 —— string Description
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; private set; }
        #endregion

        #region 只读属性 - 值描述字典 —— IDictionary<string, string> ValueDescriptions
        /// <summary>
        /// 只读属性 - 值描述字典
        /// </summary>
        /// <remarks>键：变量值，值：变量值描述</remarks>
        public IDictionary<string, string> ValueDescriptions
        {
            get
            {
                return string.IsNullOrWhiteSpace(this.ValueDescriptionsStr)
                    ? new Dictionary<string, string>()
                    : this.ValueDescriptionsStr.AsJsonTo<IDictionary<string, string>>();
            }
        }
        #endregion

        #region 内部属性 - 值描述字典序列化字符串 —— string ValueDescriptionsStr
        /// <summary>
        /// 内部属性 - 值描述字典序列化字符串
        /// </summary>
        public string ValueDescriptionsStr { get; private set; }
        #endregion

        #endregion

        #region # 方法

        #region 修改变量 —— void UpdateInfo(string variableName, Guid opcServerId...
        /// <summary>
        /// 修改变量
        /// </summary>
        /// <param name="variableName">变量名称</param>
        /// <param name="opcServerId">OPC服务器Id</param>
        /// <param name="unit">单位</param>
        /// <param name="keepRecord">是否记录历史</param>
        /// <param name="description">描述</param>
        /// <param name="valueDescriptions">值描述字典</param>
        public void UpdateInfo(string variableName, Guid opcServerId, string unit, bool keepRecord, string description, IDictionary<string, string> valueDescriptions)
        {
            #region # 验证

            if (this.VariableType == VariableType.Internal)
            {
                opcServerId = Constants.OpcProxyServerId;
            }

            #endregion

            base.Name = variableName;
            this.OpcServerId = opcServerId;
            this.Unit = unit;
            this.KeepRecord = keepRecord;
            this.Description = description;
            this.ValueDescriptionsStr = valueDescriptions?.ToJson();

            //初始化关键字
            this.InitKeywords();
        }
        #endregion

        #region 初始化关键字 —— void InitKeywords()
        /// <summary>
        /// 初始化关键字
        /// </summary>
        private void InitKeywords()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(base.Number);
            builder.Append(base.Name);
            builder.Append(this.Description);

            base.SetKeywords(builder.ToString());
        }
        #endregion

        #endregion
    }
}
